﻿using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif

using Game.AIBehaviorTree;

[Serializable]
public class BTNodeBase : ScriptableObject
{
    //用于保存ScriptableObject文件 序号
    public string nodeName;
    //BNode类名，用来创建BTNode
    public string nodeType;
    //用于保存ScriptableObject文件 nodeType+nodeName
    public string showName;
    //描述信息
    public string nodeDes;
    //该节点的node
    public BNode node;
    //父节点
    public BTNodeBase nodeParent;
    //子节点
    public List<BTNodeBase> children;

    public Rect nodeRect;
    public Vector2 indexSize = new Vector2(25f,25f);
    public BTNodeGraph parentGraph;
    //在父类中的序号
    public int indexInP = -1;

    //public NodeType nodeType;
    public bool isSelected = false;
  
    protected GUISkin nodeSkin;
    protected float btnEditHeigh = 24f;


    #region SubClasses
    [Serializable]
    public class BTEditorNodeInput
    {
        public bool isOccupied = false;
        public BTNodeBase inputNode;
    }

    [Serializable]
    public class BTEditorNodeOutput
    {
        public bool isOccupied = false;
    } 
    #endregion

    public virtual void InitNode()
    {

    }

    public virtual void InitNode(BTNodeGraph nodeGraph,string nodeType,string nodeName)
    {
        nodeRect = new Rect(10f, 10f, 200f, 80f);
        Debug.Log("create node:"+nodeType);
        this.node = ScriptableObject.CreateInstance(nodeType) as BNode;
        this.nodeType = nodeType;
        nodeGraph.addNode(this);
        if(!string.IsNullOrEmpty(nodeName))
        {
            this.nodeName = nodeName;
        }else
        {
            this.nodeName = nodeGraph.numNodeIndex.ToString();
        }

        this.showName = this.nodeType + this.nodeName;
        EditorUtility.SetDirty(this);
        UtilsEditor.CreateAsset(this.node, this.showName + ".asset", BTreeEditorData.pathTreeGameData + this.parentGraph.GraphName + "/");

    }

    //添加子节点
    public void addChild(BTNodeBase nodeBase)
    {
        if(this.children == null)
        {
            this.children = new List<BTNodeBase>();
        }
        this.children.Add(nodeBase);
        nodeBase.nodeParent = this;

        this.node.AddChild(nodeBase.node);
        nodeBase.indexInP = this.node.indexOfChild(nodeBase.node);
    }

    ///删除子节点,不管节点的子节点
    public void removeChild(BTNodeBase nodeBase)
    {
        if(this.children == null)
        {
            return;
        }
        if(this.children.Contains(nodeBase))
        {
            this.children.Remove(nodeBase);
        }
        this.node.RemoveChild(nodeBase.node);


        //foreach(BTNodeBase node in nodeBase.children){
        //    nodeBase.removeChild(node);
        //}


         AssetDatabase.DeleteAsset(nodeBase.pathForNode(false)+nodeBase.showName+".asset");

        // this.parentGraph.removeNode(nodeBase);
        AssetDatabase.DeleteAsset(nodeBase.pathForNode(true)+nodeBase.showName + ".asset");
        EditorUtility.SetDirty(this);
    }
    //将自己删除,并将自己的所有子节点删除
    public void removeSelf()
    {
        if (this.children != null && this.children.Count > 0)
        {
            for(int i = this.children.Count -1;i > -1; i--)
            {
                this.children[i].removeSelf();
            }
            //foreach (BTNodeBase node in this.children)
            //{
            //    node.removeSelf();
                
            //}
        }

        
        this.parentGraph.removeNode(this);
        if(this.nodeParent != null)
        {
            this.nodeParent.removeChild(this);
        }
        else
        {
            this.parentGraph.removeRoot();
            AssetDatabase.DeleteAsset(this.pathForNode(false) + this.showName + ".asset");
            AssetDatabase.DeleteAsset(this.pathForNode(true) + this.showName + ".asset");
        }


        // EditorUtility.SetDirty(this);

    }

    ///复制该节点以及所有子节点
    public BTNodeBase copyAllChildren(BTNodeBase parent, BTNodeGraph newGraph = null)
    {
        BTNodeBase cloneNode = this.copy(newGraph);
        if(parent != null)
        {
            cloneNode.nodeParent = parent;
            cloneNode.node._nodeParent = parent.node;
        }
        
        for(int i = 0; i < cloneNode.children.Count; i++)
        {
            cloneNode.children[i] = cloneNode.children[i].copyAllChildren(cloneNode);
        }
        return cloneNode;
    }

    //只复制该节点
    public BTNodeBase copy(BTNodeGraph newGraph = null)
    {
        BTNodeBase cloneNode = Instantiate<BTNodeBase>(this);
        BNode node = Instantiate<BNode>(this.node);
        BTNodeGraph graph;
        if(newGraph == null)
        {
            graph = this.parentGraph;
        }
        else
        {
            graph = newGraph;
        }
        graph.addNode(cloneNode);
        cloneNode.nodeName = (graph.numNodeIndex).ToString();
        cloneNode.showName = cloneNode.nodeType + cloneNode.nodeName;
        cloneNode.node = node;
        cloneNode.isSelected = false;

        UtilsEditor.CreateAsset(cloneNode, cloneNode.showName + ".asset"
                    ,this.pathForNode(true));
        UtilsEditor.CreateAsset(cloneNode.node, cloneNode.showName + ".asset"
                    ,this.pathForNode(false));

        return cloneNode;
    }

    ///移动该节点及所有子节点的位置
    public void moveAllNode(Vector2 offset)
    {
        this.nodeRect.x += offset.x;
        this.nodeRect.y += offset.y;
        if(this.children != null && this.children.Count > 0)
        {
            foreach(BTNodeBase node in this.children)
            {
                node.moveAllNode(offset);
            }
        }
    }

///获取asset保存路径，isEditorData = true为编辑器数据
public string pathForNode(bool isEditorData)
{
    if(isEditorData)
    {
        return BTreeEditorData.pathTreeEditorData+this.parentGraph.name+"/";
    }
    else
    {
        return BTreeEditorData.pathTreeGameData + this.parentGraph.name+"/";
    }
}

    ///在某个子节点前插入节点
    /// <summary>
    /// 在prenede前面插入
    /// </summary>
    /// <param name="prenode">如果为空则为普通插入</param>
    /// <param name="node"></param>
	public void InsertChildBefore( BTNodeBase prenode , BTNodeBase node )
	{
        if(prenode == null)
        {
            this.addChild(node);
            return;
        }
        int index = this.children.IndexOf(prenode);
        if(index < 0)
        {
            Debug.Log("InsertChildBefore failed,prenode don't exist");
            return;
        }

        this.children.Insert(index,node);
        node.nodeParent = this;

        for(int i = index; i < this.children.Count; i++)
        {
            this.children[i].indexInP = i;
            EditorUtility.SetDirty(this.children[i]);
           
        }
        EditorUtility.SetDirty(this);
         AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
    }   

    public virtual void UpdateNode(Event e,Rect viewRect)
    {
       // ProcessEvent(e, viewRect);

    }

    void ProcessEvent(Event e,Rect viewRect)
    {
        if(isSelected)
        {
            if (e.type == EventType.MouseDrag)
            {
                Rect realViewRect = viewRect;
                Vector2 offset = BTNodeEditorWindow.getWorkViewOffset();
                if(offset.y > 0)
                {
                    realViewRect.y += offset.y + 20f;
                }
                
                if (realViewRect.Contains(e.mousePosition))
                {
                    nodeRect.x += e.delta.x;
                    nodeRect.y += e.delta.y;
                }
            }
        }
        
        
    }

#if UNITY_EDITOR
public virtual void UpdateNodeGUI(Event e,Rect viewRect,GUISkin viewSkin)
    {
        ProcessEvent(e, viewRect);

        DrawChildrenLines();

        Rect indexRect = new Rect(nodeRect.x - indexSize.x,
                                nodeRect.y + (nodeRect.height - indexSize.y) / 2,
                                indexSize.x, indexSize.y);

        string skinName;
        if (!isSelected)
        {
            skinName = "NodeDefault";
        }
        else
        {
            skinName = "NodeSelected";
        }
        GUI.Box(nodeRect, new GUIContent(nodeType), viewSkin.GetStyle(skinName));
        if(this.nodeDes != null)
        {
            Rect labelRect = nodeRect;
            labelRect.y += nodeRect.height/2;
            labelRect.height *= 0.5f;
            GUI.Label(labelRect,this.nodeDes,BTreeEditorData.instance.labelStyle);
        }
        
        if (this.indexInP >= 0)
        {
            GUI.Box(indexRect, new GUIContent(this.indexInP.ToString()), viewSkin.GetStyle(skinName));
        }
        else
        {
            GUI.Box(indexRect, new GUIContent("R"), viewSkin.GetStyle(skinName));
        }

        EditorUtility.SetDirty(this); 
        if(this.isSelected)
        {
            EditorUtility.SetDirty(this.node);
        }
    }

    public void moveNode(Vector2 deltaPos)
    {
        nodeRect.x += deltaPos.x;
        nodeRect.y += deltaPos.y;
    }

    //画线连接子节点
    void DrawChildrenLines()
    {
        if(this.children == null || this.children.Count == 0)
        {
            return;
        }
        Handles.BeginGUI();
        Handles.color = Color.white;
        
        Vector3 rightCenter = new Vector3(this.nodeRect.x + this.nodeRect.width, 
                                          this.nodeRect.y + this.nodeRect.height / 2, 0f);
        foreach(BTNodeBase node in this.children)
        {
            Handles.DrawAAPolyLine(4.0f,rightCenter,
                         new Vector3(node.nodeRect.x,
                                     node.nodeRect.y + node.nodeRect.height / 2, 0f));
           // Handles.DrawLine(rightCenter,
                        //  new Vector3(node.nodeRect.x,
                        //              node.nodeRect.y + node.nodeRect.height / 2, 0f));
        }
        


        Handles.EndGUI();
    }

    public virtual void DrawNodeProperties()
    {
        if(!this.isSelected)
        {
            return;
        }
        GUILayout.BeginHorizontal();
        nodeDes = EditorGUILayout.TextField("Node Description:",nodeDes);
        GUILayout.EndHorizontal();
        GUILayout.Space(10f);
        Editor editor = Editor.CreateEditor(this.node);
        editor.OnInspectorGUI();
    }
#endif
}
